<!DOCTYPE html>
<html lang="en">
    <head>
    <meta charset="UTF-8">
    </head>
    <body>
        <script>
            // 把字符串转换成 node 数组
            var str="<p>1.题目,(),题目部份。 </p><p>A:答案A</p><p>B:答案B</p><p>C:答案C</p><p>D:答案D</p><p>正确答案为：B</p><p>解析：有的题目可能会有解析 </p><p>2. 题目,(),题目部份。是（B） </p><p>A:答案A</p><p>B:答案B</p><p>C:答案C</p><p>3.题目,(),题目部份。 </p><p>A:答案A</p><p>B:答案B</p><p>C:答案C</p><p>D:答案D</p><p>C:答案E</p><p>D:答案F</p><p>正确答案为：ABC</p><p>4. 题目,(),题目部份。(B) </p><p>A:答案A</p><p>B:答案B</p><p>C:答案C</p><p>D:答案D</p><p>5.题目部份。  </p><p>正确  错误  </p><p>正确答案为：正确 </p><p>解析：有的题目可能会有解析 </p><p>6.题目部份。（正确）  </p><p>A:正确</p><p>B:错误</p>"
            var temp=document.createElement("div");
            temp.innerHTML=str;
            var nodeList=temp.children;

            class Cr{
                /** @param {CrNode[]} CrNodes
                 */
                constructor(CrNodes){
                    this.crs=CrNodes;
                    this.qObjs=[];
                }
                /** @param {Element[]} elements 
                 * @returns {QOBJ[]} 返回 QOBJ 数组
                 */
                loadElement(elements){
                    this.qObjs=[];
                    for(var i=0;i<elements.length;++i){
                        for(var j=this.crs.length-1;j>=0;--j){
                            if(this.crs[j].regexp.test(elements[i].innerHTML)){
                                this.crs[j].callback.call(this,elements[i].innerHTML);
                                this.crs=this.crs[j].next;
                                j=this.crs.length-1;
                                break;
                            }
                        }
                    }
                    for(var i=this.qObjs.length-1;i>=0;--i){
                        if(!this.qObjs[i].QBType){
                            var tempStr=this.qObjs[i].answer,typeStr;
                            if(tempStr.length>1){
                                if((/^\w+/).test(tempStr)){
                                    typeStr="MC";
                                }else{
                                    typeStr="JD";
                                    if(this.qObjs[i].answer.indexOf("正确")!=-1){
                                        this.qObjs[i].answer="A";
                                    }else{
                                        this.qObjs[i].answer="B";
                                    }
                                }
                            }else{
                                typeStr="SC";
                            }
                            this.qObjs[i].QBType=typeStr;
                        }
                    }
                    return this.qObjs;
                }
            }
            class CrNode{
                /** @param {RegExp} regexp       匹配字符串的正则表达式
                 * @param {function} callback   callback.call(Cr,elements.innerHTML);
                 * @param {RegExp[]} next  匹配到之后修改当前的匹配
                 */
                constructor(regexp,callback,next){
                    this.regexp=regexp;
                    this.next=next;
                    this.callback=callback;
                }
            }
            class QOBJ{
                constructor(){
                    this.id=0;
                    this.title="";
                    this.answer="";
                    this.analysis="";
                    this.QBType="";
                }
                /** @param {String} str
                 */
                addOption(str){
                    var i=0,tempString="option"+String.fromCharCode(i+65);
                    while(this[tempString]){
                        ++i;
                        tempString="option"+String.fromCharCode(i+65);
                    }
                    this[tempString]=str;
                }
                getOptionLength(){
                    var i=0,tempString="option"+String.fromCharCode(i+65);
                    while(this[tempString]){
                        ++i;
                        tempString="option"+String.fromCharCode(i+65);
                    }
                    return i;
                }
            }

            var titleCr=new CrNode(/^[0-9]+\.[.\n\r]*/,function(str){
                var i=this.qObjs.length-1;
                i=this.qObjs.push(new QOBJ());
                var temp=str.match((/[\(（]+([\w正确错误]+)[\)）]+/));
                if(temp){
                    this.qObjs[i-1].answer=temp[1];
                }
                this.qObjs[i-1].title=str.slice(str.indexOf('.')+1);
                this.qObjs[i-1].id=parseInt(str.slice(0,str.indexOf('.')));
            });
            var optionCr=new CrNode(/^[a-z]|[A-Z]+[:：][.\n\r]*/,function(str){
                var i=this.qObjs.length-1;
                this.qObjs[i].addOption(str.slice(str.indexOf(/[:：]/)+1));
            });
            var optionBoolCr=new CrNode(/正确 +错误 */,function(str){
                var i=this.qObjs.length-1;
                this.qObjs[i].addOption("正确");
                this.qObjs[i].addOption("错误");
                this.qObjs[i].QBType="JD"
            });
            var answerCr=new CrNode(/^正确答案为[：:][.\n\r]*/,function(str){
                var i=this.qObjs.length-1;
                var tempStr=str.slice("正确答案为：".length),typeStr="";

            });
            var analysisCR=new CrNode(/^解析[：:][.\n\r]*/,function(str){
                var i=this.qObjs.length-1;
                this.qObjs[i].analysis=str.slice("解析：".length);
            });
            titleCr.next=[optionCr,optionBoolCr];
            optionCr.next=[titleCr,optionBoolCr,optionCr,answerCr];
            optionBoolCr.next=[titleCr,optionBoolCr,optionCr,answerCr];
            answerCr.next=[titleCr,analysisCR];
            analysisCR.next=[titleCr];
            
            var d=new Cr([titleCr]);
            var c=d.loadElement(nodeList);

            console.log(JSON.stringify(c));
        </script>
    </body>
</html>